package edu.rit.varapp.utilities;

import edu.rit.varapp.datalayer.Customer;
import edu.rit.varapp.datalayer.Message;
import edu.rit.varapp.datalayer.Module;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

/**
 * JTableUtils is a utilities class that can retrieve data from a JTable.
 * @author Eric Kisner
 */
public class JTableUtils {

    /**
     * Returns all values of a JTable as a Collection of a collection of strings, which represents
     * a Collection of rows.
     * @param numRows The number of rows in the JTable.
     * @param numColumns The number of columns in the JTable.
     * @param table The JTable we want to extract data from.
     * @return A collection of 'rows'.
     */
    public static ArrayList<ArrayList<String>> dataFromTable( JTable table ) {
        TableModel m = table.getModel();
        int numRows = m.getRowCount();
        int numColumns = m.getColumnCount();
        ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
        for( int i = 0; i < numRows; i++ ) {
            ArrayList<String> row = new ArrayList<String>();
            for( int j = 0; j < numColumns; j++ ) {
                String cellVal = (String) m.getValueAt( i, j );
                if( cellVal != null ) cellVal = cellVal.trim();
                row.add( cellVal );
            }
            ret.add( row );
        }
        return ret;
    }

    /**
     * Returns all values of a JTable with a SINGLE row of data. This should only be used when the JTable is
     * known to have one row of information, and no more.
     * @see JTableUtils#dataFromTable(int, int, javax.swing.JTable)
     */
    public static ArrayList<String> singleDataFromTable( JTable table ) {
        TableModel m = table.getModel();
        int numColumns = m.getColumnCount();
        ArrayList<String> ret = new ArrayList<String>();
        for( int i = 0; i < 1; i++ ) {
            for( int j = 0; j < numColumns; j++ ) {
                ret.add( ((String) m.getValueAt( i, j )).trim() );
            }
        }
        return ret;
    }

    /**
     * This method will return a JTable that has been populated according to the header information, and actual
     * customer information. In order to return a correctly-formatted JTable, you must specify exactly what
     * customer information you want to display by correctly populating the header array. For example:
     * If you want to display Contact name, Company name, and email, the header array MUST have "Contact Name",
     * "Company Name", and "Email" as its contents. This will allow the method to retrieve only this information
     * from the Customer data. It is OK to have spaces within the header contents (for formatting purposes), as
     * the method will replace all white-space.
     * 
     * @param header The header information for the JTable. This also specifies what information we want to display
     *               in the JTable.
     * @param customers The actual list of customers that we want to display.
     * @param editable Flag to say if we want the cells in the JTable to be editable.
     * @return A JTable that has been populated according to the header array and list of customers.
     */
    public static JTable getCustomerTable( String[] header, List<Customer> customers, final boolean editable ) {
        ArrayList<ArrayList<String>> rowData = new ArrayList<ArrayList<String>>();
        for( Customer customer : customers ) {
            ArrayList<String> aRow = new ArrayList<String>();
            HashMap<String, String> customerMap = customer.asMap( false );
            for( int i = 0; i < header.length; i++ ) {
                String trimmedHeader = header[i].replaceAll( " ", "" );
                aRow.add( customerMap.get( trimmedHeader ) );
            }
            rowData.add( aRow );
        }

        Object[][] arrRowData = new Object[rowData.size()][header.length];
        for( int i = 0; i < rowData.size(); i++ ) {
            arrRowData[i] = rowData.get( i ).toArray();
        }

        DefaultTableModel model = new DefaultTableModel( arrRowData, header );
        final JTable table = new JTable( model ) {

            @Override
            public boolean isCellEditable( int row, int column ) {
                return editable; //Disallow any table editing.
            }
        };
        return table;
    }

    /**
     * Returns a JTable populated with Modules.
     * @see #getCustomerTable(java.lang.String[], java.util.ArrayList, boolean)
     */
    public static JTable getModuleTable( String[] header, List<Module> modules, final boolean editable ) {
        ArrayList<ArrayList<String>> rowData = new ArrayList<ArrayList<String>>();
        for( Module module : modules ) {
            ArrayList<String> aRow = new ArrayList<String>();
            HashMap<String, String> modulesMap = module.asMap( false );
            for( int i = 0; i < header.length; i++ ) {
                String trimmedHeader = header[i].replaceAll( " ", "" );
                aRow.add( modulesMap.get( trimmedHeader ) );
            }
            rowData.add( aRow );
        }

        Object[][] arrRowData = new Object[rowData.size()][header.length];
        for( int i = 0; i < rowData.size(); i++ ) {
            arrRowData[i] = rowData.get( i ).toArray();
        }

        DefaultTableModel model = new DefaultTableModel( arrRowData, header );
        final JTable table = new JTable( model ) {

            @Override
            public boolean isCellEditable( int row, int column ) {
                return editable; //Disallow any table editing.
            }
        };
        return table;
    }

    /**
     * Returns a JTable populated with Messages.
     * @see #getCustomerTable(java.lang.String[], java.util.ArrayList, boolean)
     */
    public static JTable getMessagesTable( String[] header, List<Message> messages, final boolean editable ) {
        ArrayList<ArrayList<String>> rowData = new ArrayList<ArrayList<String>>();
        for( Message message : messages ) {
            ArrayList<String> aRow = new ArrayList<String>();
            HashMap<String, String> modulesMap = message.asMap( false );
            for( int i = 0; i < header.length; i++ ) {
                String trimmedHeader = header[i].replaceAll( " ", "" );
                aRow.add( modulesMap.get( trimmedHeader ) );
            }
            rowData.add( aRow );
        }

        Object[][] arrRowData = new Object[rowData.size()][header.length];
        for( int i = 0; i < rowData.size(); i++ ) {
            arrRowData[i] = rowData.get( i ).toArray();
        }

        DefaultTableModel model = new DefaultTableModel( arrRowData, header );
        final JTable table = new JTable( model ) {

            @Override
            public boolean isCellEditable( int row, int column ) {
                return editable; //Disallow any table editing.
            }
        };
        return table;
    }
}
